package plus.easydo.starter.oauth.server.configure;

import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import plus.easydo.starter.oauth.server.properties.Oauth2ServerProperties;

import javax.annotation.Resource;

/**
 * oauth2.0服务配置
 *
 * @author yuzhanfeng
 */
@Configuration
@EnableAuthorizationServer
@Import({ServerBeanConfig.class})
@EnableConfigurationProperties(Oauth2ServerProperties.class)
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true)
public class AuthorizationServerAutoConfiguration extends AuthorizationServerConfigurerAdapter {

    @Resource(name = "serverBeanConfig")
    private ServerBeanConfig serverBeanConfig;

    /**
     * 配置客户端信息
     *
     * @param clients ClientDetailsServiceConfigurer
     * @throws Exception e
     */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        /*使用数据库持久化客户端信息*/
        clients.withClientDetails(serverBeanConfig.getClientDetailsService());
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
        endpoints
                /*自定义异常捕获*/
                .exceptionTranslator(serverBeanConfig.getWebResponseExceptionTranslator())
                /*重写 AccessTokenConverter（DefaultAccessTokenConverter）
                 中的UserAuthenticationConverter （DefaultUserAuthenticationConverter）
                 实现获取tokenInfo操作时返回全部信息
                 */
                .accessTokenConverter(serverBeanConfig.getAccessTokenConverter())
                /*注入authenticationManager来支持password模式*/
                .authenticationManager(serverBeanConfig.getAuthenticationManager())
                /*设置授权码服务*/
                .authorizationCodeServices(serverBeanConfig.getAuthorizationCodeServices())
                /*设置token服务*/
                .tokenServices(serverBeanConfig.getAuthorizationServerTokenServices())
                /*允许的令牌端点请求方法*/
                .allowedTokenEndpointRequestMethods(HttpMethod.POST, HttpMethod.GET)
                /*将oauth2.0的默认授权请求路径转至自定义的授权控制层请求路径*/
                .pathMapping("/oauth/confirm_access", serverBeanConfig.properties().getConfirmAccessPath());
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) {
        security
                /*设置密码编码器*/
                .passwordEncoder(new BCryptPasswordEncoder())
                /*放行令牌访问*/
                .tokenKeyAccess("permitAll()")
                /*放行令牌校验*/
                .checkTokenAccess("permitAll()")
                /*允许客户端进行表单验证*/
                .allowFormAuthenticationForClients()
        ;
    }

}
